/*******************************************************************************
 * Copyright (c) 2001-2003 Boris Pruessmann and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v0.5 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation.
 ******************************************************************************/
package net.sourceforge.perforce.core.internal.api;

import com.google.common.collect.Lists;

import net.sourceforge.perforce.api.IPerforceCommand;
import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.api.IDescribeResult;
import net.sourceforge.perforce.core.syncinfo.ResourceSyncInfo;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * ClientUser object for the 'p4 describe' command.
 * 
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 */
public class Describe extends AbstractPerforceCommand implements IPerforceCommand {
  // ---------------------------------------------------------------------------
  // Private Variables

  /** Stores the result of the operation. */
  private Result result = new Result();

  // --------------------------------------------------------------- Public
  // Static Factory Methods

  /**
   * Convenience method for creating instances of Describe.
   * 
   * @return the new Describe instance.
   */
  public static final Describe newInstance() {
    MultiStatus status = new MultiStatus(PerforceCorePlugin.ID, IStatus.OK, "", null);
    return new Describe(status);
  }

  // ------------------------------------------------------------------------
  // Private Constructors

  /**
   * Constructor for Describe.
   * 
   * @param status the MultiStatus.
   */
  private Describe(MultiStatus status) {
    super(status);
  }

  // -------------------------------------------------------- Public Methods
  // (IClientUserDelegate)

  @Override
  public void outputStat(Map<String, ?> strDict) {
    result.setChangelist(Helper.safeGetInteger(strDict, "change")); //$NON-NLS-1$
    result.setUserName(Helper.safeGetString(strDict, "user")); //$NON-NLS-1$
    result.setClientName(Helper.safeGetString(strDict, "client")); //$NON-NLS-1$
    result.setDate(Helper.safeGetDate(strDict, "time")); //$NON-NLS-1$
    result.setDescription(Helper.safeGetString(strDict, "desc")); //$NON-NLS-1$
    result.setStatus(Helper.safeGetString(strDict, "status")); //$NON-NLS-1$

    List<ResourceSyncInfo> affectedFiles = Lists.newArrayList();
    for (int i = 0; strDict.containsKey("depotFile" + i); i++) //$NON-NLS-1$
    {
      ResourceSyncInfo resourceSyncInfo = new ResourceSyncInfo();
      resourceSyncInfo.setDepotFileName(Helper.safeGetString(strDict, "depotFile" + i)); //$NON-NLS-1$
      resourceSyncInfo.setAction(Helper.safeGetString(strDict, "action" + i)); //$NON-NLS-1$
      resourceSyncInfo.setHeadType(Helper.safeGetString(strDict, "type" + i)); //$NON-NLS-1$
      resourceSyncInfo.setHeadRev(Helper.safeGetInteger(strDict, "rev" + i).intValue()); //$NON-NLS-1$

      affectedFiles.add(resourceSyncInfo);
    }

    result.setAffectedFiles(affectedFiles.toArray(new ResourceSyncInfo[affectedFiles.size()]));
  }

  // ----------------------------------------------------------- Public Methods
  // (IPerforceCommand)

  public String getCommand() {
    return "describe"; //$NON-NLS-1$
  }

  @Override
  public IStatus getStatus() {
    return getMultiStatus();
  }

  //----------------------------------------------------------------------------
  // -- Public Methods

  /**
   * Returns the result of the operation.
   * 
   * @return the result object.
   */
  public IDescribeResult getResult() {
    return result;
  }

  // ----------------------------------------------------------------------
  // Private Nested Classes

  /**
   * Implementation of the IDescribeResult. Stores information provided by the
   * 'p4 describe' command.
   * 
   * @see IDescribeResult
   */
  private static class Result implements IDescribeResult {
    // -----------------------------------------------------------------------
    // Private Variables

    /** Stores the changelist number. */
    private Integer changelist;
    /** Stores the username. */
    private String userName;
    /** Stores the client name. */
    private String clientName;
    /** Stores the submission date. */
    private Date date;
    /** Stores the description. */
    private String description;
    /** Stores the status. */
    private String status;
    /** Stores the affected files. */
    private ResourceSyncInfo[] affectedFiles;

    //--------------------------------------------------------------------------
    // Public Methods

    public Integer getChangelist() {
      return changelist;
    }

    public String getUserName() {
      return userName;
    }

    public String getClientName() {
      return clientName;
    }

    public Date getDate() {
      return date;
    }

    public String getDescription() {
      return description;
    }

    public String getStatus() {
      return status;
    }

    public ResourceSyncInfo[] getAffectedFiles() {
      return affectedFiles;
    }

    //--------------------------------------------------------------------------
    // ------- Methods

    /**
     * Sets the affectedFiles.
     * 
     * @param affectedFiles The affectedFiles to set
     */
    void setAffectedFiles(ResourceSyncInfo[] affectedFiles) {
      this.affectedFiles = affectedFiles;
    }

    /**
     * Sets the changelist.
     * 
     * @param changelist The changelist to set
     */
    void setChangelist(Integer changelist) {
      this.changelist = changelist;
    }

    /**
     * Sets the clientName.
     * 
     * @param clientName The clientName to set
     */
    void setClientName(String clientName) {
      this.clientName = clientName;
    }

    /**
     * Sets the date.
     * 
     * @param date The date to set
     */
    void setDate(Date date) {
      this.date = date;
    }

    /**
     * Sets the description.
     * 
     * @param description The description to set
     */
    void setDescription(String description) {
      this.description = description;
    }

    /**
     * Sets the status.
     * 
     * @param status The status to set
     */
    void setStatus(String status) {
      this.status = status;
    }

    /**
     * Sets the userName.
     * 
     * @param userName The userName to set
     */
    void setUserName(String userName) {
      this.userName = userName;
    }
  }
}
